/* Class Supported Code */
Function.prototype.binding = function() {
    if (arguments.length < 2 && typeof arguments[0] == "undefined") return this;
    var __method = this, args = jQuery.makeArray(arguments), object = args.shift();
    return function() {
        return __method.apply(object, args.concat(jQuery.makeArray(arguments)));
    }
}

var Class = function(subclass){
 subclass.setOptions = function(options){
  this.options = jQuery.extend({}, this.options,options);
  for(var key in options){
   if(/^on[A-Z][A-Za-z]*$/.test(key)){
    $(this).bind(key,options[key]);
   }
  }
 }
    var fn =  function(){
        if(subclass._init && typeof subclass._init == 'function'){
            this._init.apply(this,arguments);
        }
    }
    if(typeof subclass == 'object'){
        fn.prototype = subclass;
    }
    return fn;
}


/* Add your code here*/
var FilterPanel = new Class({
    options: {
        containerId: null,
        filterElements: null,
        legendTitle: "",
        sAjaxSource: "",
        errorMessage: null,
        fnSubmit: function() { },
        onBeforeStart: function() { },
        onActionbtnClick: function() { }
    },

    _init: function(options) {
        this.setOptions(options);
        this.container = $('#' + this.options.containerId);
        this.elements = this.options.filterElements;
        this.title = this.options.legendTitle;
        this.fnSubmit = this.options.fnSubmit;
        this.createFilter();
        this.initEvents();
    },

    createFilter: function() {
        var fieldPanel = $("<fieldset></fieldset>");
        var title = $("<legend>" + this.title + "</legend>");
        title.appendTo(fieldPanel);

        var table = $("<table></table>");
        var spans = new Array();
        var boxes = new Array();

        // Create element for each filter condition
        for (var i = 0; i < this.elements.length; i++) {
            var labelName = this.elements[i].sLabelName;
            var name = this.elements[i].sName;
            var id = this.elements[i].sId;
            var isAutoComplete = this.elements[i].bAuto;
            var maxLength = this.elements[i].sMaxLength;
            var newElementTr = $("<tr></tr>");
            var newElementTd = $("<td></td>");
            var nameSpan = $("<span>" + labelName + "</span>");
            nameSpan.appendTo(newElementTd);

            var fieldBox = $("<input type='text' id='" + id + "' name='" + name + "' maxlength='" + maxLength + "' value='" + this.elements[i].defaultValue + "' tabindex='" + (i + 1) + "'/>");
            fieldBox.addClass("value-field");

            // If the box allow to AutoComplete, bind it to AutoComplete class
            if (isAutoComplete) {
                fieldBox.addClass("AutoComplete");
            }

            fieldBox.appendTo(newElementTd);
            newElementTd.appendTo(newElementTr);
            newElementTr.appendTo(table);

            spans.push(nameSpan);
            boxes.push(fieldBox);
        }

        // create fielter button
        var submitBtn = $("<tr><td align='right'><br /><input type='button' id='fliterBtn' value='Filter' tabindex='" + (i + 2) + "'/>&nbsp;&nbsp;<input type='button' value='Reset' id='clearAllBtn' tabindx='" + (i + 3) + "' /></td></tr>");
        submitBtn.appendTo(table);
        table.appendTo(fieldPanel);
        fieldPanel.appendTo(this.container);

        $("#fliterBtn").bind("click", this.submitFilter.binding(this));
        $("#clearAllBtn").bind("click", this.clearAllFields.binding(this));

        this.widthCalculation(spans, boxes);
        // this.clearAllFields(boxes);
    },

    widthCalculation: function(spans, boxes) {
        for (var i = 0; i < spans.length; i++) {
            var boxWidth = 250 - spans[i].width();
            boxes[i].css("width", "" + boxWidth + "px");
        }
    },

    clearAllFields: function(boxes) {

        for (var i = 0; i < boxes.length; i++) {
            boxes[i].val("");
        }

        this.submitFilter();
    },

    submitFilter: function() {
        var objFilter = JSON.covert2Json(this.container, "value-field");
        this.fnSubmit(objFilter);
    },

    initEvents: function() {
    }
});



$.fn.dataTableExt.oApi.fnChangeAjaxData = function(oSettings, sNewSource) {
    oSettings.sAjaxSource = sNewSource;
    this.fnClearTable(this);
    this.oApi._fnProcessingDisplay(oSettings, true);
}

$.fn.dataTableExt.oApi.fnReloadAjax = function(oSettings, sNewSource, fnCallback, bStandingRedraw) {
    if (typeof sNewSource != 'undefined' && sNewSource != null) {
        oSettings.sAjaxSource = sNewSource;
    }
    this.oApi._fnProcessingDisplay(oSettings, true);
    var that = this;
    
    if (oSettings.oFeatures.bServerSide) {

        that.oApi._fnClearTable(oSettings);
        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
        that.fnDraw(that);
    } else {
        var iStart = oSettings._iDisplayStart;

        oSettings.fnServerData(oSettings.sAjaxSource, null, function(json) {
            /* Clear the old information from the table */
            that.oApi._fnClearTable(oSettings);

            /* Got the data - add it to the table */
            for (var i = 0; i < json.aaData.length; i++) {
                that.oApi._fnAddData(oSettings, json.aaData[i]);
            }

            oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
            that.fnDraw(that);

            if (typeof bStandingRedraw != 'undefined' && bStandingRedraw === true) {
                oSettings._iDisplayStart = iStart;
                that.fnDraw(false);
            }

            that.oApi._fnProcessingDisplay(oSettings, false);

            /* Callback user function - for event handlers etc */
            if (typeof fnCallback == 'function' && fnCallback != null) {
                fnCallback(oSettings);
            }
        });
    }

}

// AccordionTable Class
var AccordionTable = new Class({
    options: {
        sDataSource: "",
        sDetailUrl: "",
        containerId: "",
        bServerSide: false,
        aoCloumns: undefined
    },
    _init: function(options) {
        this.setOptions(options);
        this.queryObjet = new Object();
        this.oTable = null;
        this.container = $("#" + this.options.containerId);
        this.dataSource = this.options.sDataSource;
        this.detailUrl = this.options.sDetailUrl;
        this.columnNum = this.container.find("tr:first").children().length;
        this.initTable();
    },

    initTable: function() {
        this.oTable = this.container.dataTable({
            "bAutoWidth": false,
            "bProcessing": true,
            "bServerSide": this.options.bServerSide,
            "sPaginationType": "full_numbers",
            "aoColumns": this.options.aoCloumns,
            "bSort": false,
            "iDisplayLength": 15,
            "sAjaxSource": this.dataSource,
            "fnRowCallback": function(nRow, aData, iDisplayIndex) {
                // initial accordion as 'Closed' state
                $('td:eq(0)', nRow).removeClass("accordion-close").addClass("Accordion accordion-open").empty().attr("id", aData[0]).bind("click", nRow, this.accordionClick.binding(this));
                $(nRow).hover(function() { $(this).addClass("highlight"); }, function() { $(this).removeClass("highlight"); });
                return nRow;
            } .binding(this),
            "fnServerData": function(sSource, aoData, fnCallback) {
                /* Add some extra data to the sender if you have*/
                var data = aoData;
                if (this.options.bServerSide == true) {
                    var query = {
                        QueryObject: this.queryObjet,
                        sEcho: aoData[0].value,
                        iColumns: aoData[1].value,
                        sColumns: aoData[2].value,
                        iDisplayStart: aoData[3].value,
                        iDisplayLength: aoData[4].value,
                        sSearch: aoData[5].value
                    };

                    data = JSON.stringify(query);
                } else {
                
                    data = JSON.stringify(this.queryObjet);
                }


                PIM.Ajax.setupStandardAjax();
                PIM.Ajax.getJSON(sSource, data, function(json) {
                    /* Do whatever additional processing you want on the callback, then tell DataTables */
                    fnCallback(json);
                });
            } .binding(this)
        });

        // hide the length
        $("#" + this.options.containerId + "_length").css("display", "none");
    },

    fnReLoadAajx: function(query) {
        this.queryObjet = query;
        this.oTable.fnReloadAjax();
    },

    openAccordion: function(trEle) {
        this.closeAccordion();
        var id = $('td:eq(0)', trEle).attr("id");
        var newTr = $("<tr id='AccordionContainer'><td colspan='" + this.columnNum + "' style='width:100%'></td></tr>").insertAfter(trEle);
        this.requestHtmlFromServer(id, newTr);
    },

    closeAccordion: function() {
        $("#AccordionContainer").remove();
        $(".accordion-close").removeClass("accordion-close").addClass("accordion-open");
    },

    requestHtmlFromServer: function(id, container) {
        // load data from server
        $.ajax({
            type: "POST",
            data: { Id: id },
            url: this.detailUrl,  // as a parameter when refactor
            dataType: "html",
            success: function(html) {
                $("td:eq(0)", container).append(html).find("div:first").slideToggle(500);
                $(container).prev().children("td:eq(0)").removeClass("accordion-open").addClass("accordion-close");
            }
        });
    },

    accordionClick: function(params) {
        if ($(params.data).children("td:eq(0)").hasClass("accordion-close")) {
            // better user experience for closing
            $("#AccordionContainer").find("div:first").slideToggle(500, this.closeAccordion);
        } else {
            this.openAccordion(params.data);
        }
    }
});

JSON.covert2Json = JSON.covert2Json || function(ele, className) {
    var json = eval('(' + JSON.cover2JsonStr(ele, className) + ')');
    return json;
}

JSON.cover2JsonStr = JSON.cover2JsonStr || function(ele, className) {
    var strJson = "{";

    var values = $(ele).find("." + className);
    for (var i = 0, max = values.length; i < max; i++) {
        var val = $(values[i]).val() != '' ? $(values[i]).val() : $(values[i]).text();
        if (val != "") {
            strJson += $(values[i]).attr("name") + ":" + "\'" + val + "\',";
        }
    }

    if (strJson != "{") {
        strJson = strJson.substring(0, strJson.length - 1);
        strJson += "}";
    } else {
        strJson = "{}";
    }

    return strJson;
}

JSON.cover2JsonAry = JSON.cover2JsonAry || function(ele) {
    var json = eval('(' + JSON.cover2JsonAryStr(ele) + ')');
    return json;
}

JSON.cover2JsonAryStr = JSON.cover2JsonAryStr || function(ele) {
    var strJson = "[";

    var aryRows = $(ele).find(".field-row");

    for (var i = 0, max = aryRows.length; i < max; i++) {
        strJson += JSON.cover2JsonStr(aryRows[i], "row-value") + ",";
    }

    if (strJson != "[") {
        strJson = strJson.substring(0, strJson.length - 1);
        strJson += "]";
    } else {
        strJson = "[]";
    }

    return strJson;
}



JSON.conver2JsonCpxStr = JSON.conver2JsonCpxStr || function(ele) {
    var strJson = JSON.cover2JsonStr(ele, "value-field");

    strJson = strJson.substring(0, strJson.length - 1);

    if (strJson != "{") {
        strJson += ",";
    }

    var aryItems = $(ele).find(".array-field");

    for (var i = 0, max = aryItems.length; i < max; i++) {
        strJson += $(aryItems[i]).attr("name") + ":" + JSON.cover2JsonAryStr(aryItems[i]) + ",";
    }

    strJson = strJson.substring(0, strJson.length - 1);
    strJson += "}";

    return strJson;
}

JSON.conver2JsonCpx = JSON.conver2JsonCpx || function(ele) {
    var json = eval('(' + JSON.conver2JsonCpxStr(ele) + ')');
    return json;
}


// implement JSON.stringify serialization  
JSON.stringify = JSON.stringify || function(obj) {
    var t = typeof (obj);
    if (t != "object" || obj === null) {
        // simple data type  
        if (t == "string") obj = '"' + obj + '"';
        return String(obj);
    }
    else {
        // recurse array or object  
        var n, v, json = [], arr = (obj && obj.constructor == Array);
        for (n in obj) {
            v = obj[n]; t = typeof (v);
            if (t == "string") v = '"' + v + '"';
            else if (t == "object" && v !== null) v = JSON.stringify(v);
            json.push((arr ? "" : '"' + n + '":') + String(v));
        }
        return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
    }
};

/*
 * Query Box
 * Usage >>
 * containerId: 
 * queryButtonId: 
 * resetButtonId: 
 * fnBeforeQuery:
 * fnOnQuery: 
 * fnInit: 
 */

var QueryBox = new Class({
    options: {
        containerId: null,
        queryButtonId: null,
        resetButtonId: null,
        fnBeforeQuery: function() { return true; },
        fnOnQuery: function(aoData) { },
        fnInit: function() { }
    },

    _init: function(options) {
        this.setOptions(options);

        this.container = $("#" + this.options.containerId);
        this.queryButton = $("#" + this.options.queryButtonId);
        this.resetButton = $("#" + this.options.resetButtonId);
        this.fnBeforeQuery = this.options.fnBeforeQuery;
        this.fnOnQuery = this.options.fnOnQuery;

        this.initQueryBox();
        this.options.fnInit();
    },

    initQueryBox: function() {
        $("#" + this.options.containerId + " input[type='text']").addClass("query-field");
        this.queryButton.bind("click", this.query.binding(this));
        this.resetButton.bind("click", this.reset.binding(this));
    },

    query: function() {
        if (this.fnBeforeQuery()) {
            var aoData = this.serialize();
            this.fnOnQuery(aoData);
        }
    },

    reset: function() {
        $("#" + this.options.containerId + " input[type='text']").val("");
        this.queryButton.click();
    },

    serialize: function() {
        return JSON.covert2Json(this.container, "query-field");
    }

});

